home *** CD-ROM | disk | FTP | other *** search
- (**************************************************************************)
- (* This program simulates a graph environment for LaTeX. Using a list of *)
- (* parameters, it generates LaTeX commands to produce a complete graph. *)
- (* see the latexgraph.doc file for detailed documentation. *)
- (* author:Sunil Podar, podar@sbcs.csnet, ...!{allegra,philabs}!sbcs!podar *)
- (* Please quote the following date when sending bug reports. *)
- (* last update: Feb 2, 1987 (fixed bugs: wasn't doings things right when *)
- (* (0,0) was not on the graph. Also removed the printing of *)
- (* a few of the margin commands from preamble. *)
- (* last update: Oct 5, 1986 *)
- (**************************************************************************)
- program main (input,output);
- const delim = '@'; (* Latex never uses @ except for \@ for a little *)
- (* space before a sentence-ending period *)
- maxchar = 'F';(* maximum types of characters permitted for plotchar*)
- (* A..F i.e. 6 distinct chars permitted *)
- type wholeline = packed array[1..80] of char;
- tenchar = packed array[1..10] of char;
- ninechar = packed array[1..9] of char;
- twochar = packed array[1..2] of char;
- plotstufftype = record
- chardef : wholeline;
- charname : wholeline
- end;
- var
- plotstuff : array['A'..maxchar] of plotstufftype;
- error1,itsreal :boolean;
- picwd,picht,pos,Xdeltabar,
- Ydeltabar,i,Xlegloc,Ylegloc,Xdeltanum,Ydeltanum : integer;
- Xaxisstrg,Yaxisstrg,capstring,blank80,labelname,fontname : wholeline;
- legendloc,captiontwo,prepost : twochar;
- string,blank10,captiontype,fignumber : tenchar;
- plotchar,c : char;
- string9 : ninechar;
- Xscalegraph,Yscalegraph : integer;
- XGorig,YGorig,XP1orig,YP1orig,XP2orig,YP2orig : integer;
- Xscalereal,Yscalereal,xreality, yreality, xgraph, ygraph,
- unitlngth,textwd,Xorignum,Yorignum,deln,num : real;
-
- procedure strreadline(var commandstr: wholeline);
- var charac:char;
- i : integer;
- endoffile, endofline:boolean;
- begin
- i:=1;
- endoffile :=false;
- endofline:=false;
- commandstr:=blank80;
- repeat
- read(charac);
- if (i < 80) then commandstr[i] := charac; (* 80th char remains @ *)
- i := i+1;
- if eof then endoffile :=true
- else if eoln then endofline :=true
- until (endoffile or endofline);
- if (i <= 80) then commandstr[i] := delim;
- if not endoffile then readln
- end; (*strreadline*)
-
- procedure strreadword(var string: tenchar; var string9: ninechar);
- var charac:char;
- i : integer;
- begin
- i:=1;
- string:=blank10;
- read(charac);
- repeat
- string[i] := charac;
- read(charac);
- i := i+1
- until ((charac = '/') or (charac = ' ') or (i > 10) or eoln);
- (* so I'm reading the / without assigning it to string, neat *)
- if (eoln and (i <=10)) then string[i]:= charac;
- (* a kluge, to capture the last charac when using this procedure to *)
- (* read the argument. normally I use it only for parameters. *)
- for i:= 1 to 9 do string9[i] := string[i]
- end; (*strreadword*)
-
- procedure strwrite(str: wholeline);
- var i : integer;
- begin
- i := 1;
- while (str[i] <> delim) do
- begin
- write(str[i]); i := i+1
- end
- end;
-
- procedure legendread;
- var i : integer;
- temp : twochar;
- begin
- temp := ' ';
- legendloc := ' '; i := 0;
- if (not eoln) then
- repeat
- i := i+1; read(legendloc[i]);
- until (eoln) or (i >= 2) or (legendloc[i] = '/');
- if (not eoln) then if (legendloc[i] <> '/') then read(temp[1]);
- if (temp[1] = '/') or (legendloc[i] = '/')
- then readln(Xlegloc,Ylegloc)
- else readln
- end; (* legendread *)
-
- (* in the following procedures, the boolean var XorY: true => X & false => Y*)
- procedure putbars(XorY:boolean; Xpos, Ypos, deltabar, distance: integer);
- var times: integer;
- begin
- times := distance div abs(deltabar);
- if times > 0 then
- if XorY (* X *)
- then writeln('\multiput(',Xpos:1,',',Ypos:1,')(',
- deltabar:1,',0){',times:1,'}{\line(0,1){2}}')
- else writeln('\multiput(',Xpos:1,',',Ypos:1,')(0,',
- deltabar:1,'){',times:1,'}{\line(1,0){2}}');
- end; (* putbars *)
-
- (* see a note about putnumbers in the main program. *)
- (* because we may have real numbers, we can't use a counter *)
- (* in conjunction with a \multiput statement. *)
- procedure putnumbers(XorY:boolean; fixedpos, initpos:integer;
- initnum, deln:real; deltanum:integer; limit:real);
- var pos: integer;
- num: real;
- begin
- num:=initnum; pos:= initpos;
- if (abs(num) - round(abs(num) - 0.5)) > 0 then itsreal := true;
- while abs(pos) < abs(limit) do
- begin
- if XorY then (* X *)
- write('\put(',pos:1,',',fixedpos:1,'){\makebox(0,0)[t]{')
- else write('\put(',fixedpos:1,',',pos:1,'){\makebox(0,0)[r]{');
- if itsreal then writeln(num:1:2,'}}')
- else writeln(trunc(num):1,'}}');
- pos := pos + deltanum;
- num := num + deln
- end;
- end; (* putnumbers *)
-
- begin(* main *)
- (*----------------------------------*)
- (* Initializations & default values *)
- (*----------------------------------*)
- error1 := false;
- itsreal:=false;
- for i := 1 to 10 do blank10[i] := ' ';
- for i := 1 to 79 do blank80[i] := ' '; blank80[80] := delim;
- captiontype := blank10; captiontype := 'no '; (*default 'no' *)
- fignumber := blank10;
- fontname := blank80; (* just playing it safe *)
- fontname := '{normalsize}'; fontname[13] := delim;
- labelname := blank80; labelname[1] := 'n'; (* default 'no' *)
- prepost := 'no';
- unitlngth := 1.0;
- picwd := 100; picht := 100; XP1orig := 0; YP1orig := 0;
- legendloc := 'no';
- Xscalegraph := 10; Xscalereal := 10;
- Yscalegraph := 10; Yscalereal := 10;
- Xdeltabar := 5; Xdeltanum := 10;
- Ydeltabar := 5; Ydeltanum := 10;
- Xorignum := 0;
- Yorignum := 0;
- for c := 'A' to maxchar do
- begin
- plotstuff[c].chardef[1] := 'n'; (* default value is 'no' *)
- plotstuff[c].charname := blank80;
- plotstuff[c].charname[1] := c;
- plotstuff[c].charname[2] := delim
- end;
- Xlegloc := -999999;
- Ylegloc := -999999;
- strreadword(string, string9);
- while string <> '%%%%%%%%%%' do
- begin
- if string = '%pre&post?' then readln(prepost[1])
- else if string = '%unitlngth' then readln(unitlngth)
- else if string = '%font-name' then strreadline(fontname)
- else if string = '%picdimens' then readln(picwd,picht,XP1orig,YP1orig)
- else if string = '%??caption' then begin
- strreadword(captiontype, string9);
- readln
- end
- else if string = '%fignumber' then begin
- strreadword(fignumber, string9);
- readln
- end
- else if string = '%Xaxisstrg' then strreadline(Xaxisstrg)
- else if string = '%Yaxisstrg' then strreadline(Yaxisstrg)
- else if string = '%capstring' then strreadline(capstring)
- else if string = '%labelname' then strreadline(labelname)
- else if string = '%legendloc' then legendread
- else if string = '%Xdeltab:n' then readln(Xdeltabar,Xdeltanum)
- else if string = '%Xoriginum' then readln(Xorignum)
- else if string = '%Ydeltab:n' then readln(Ydeltabar,Ydeltanum)
- else if string = '%Yoriginum' then readln(Yorignum)
- else if string = '%Xratiog:r' then readln(Xscalegraph,Xscalereal)
- else if string = '%Yratiog:r' then readln(Yscalegraph,Yscalereal)
- else if string9 = '%plotchar' then
- strreadline(plotstuff[string[10]].chardef)
- else if string9 = '%plotname' then
- strreadline(plotstuff[string[10]].charname)
- else begin
- readln;writeln;
- writeln('**********************************************');
- writeln('error: unknown string: "',string,'"');
- writeln('**********************************************');
- error1:=true
- end;
- string := blank10;
- strreadword(string, string9)
- end; (* while *)
- readln; (* this readln is to finish reading the %%%%%.. line*)
-
- (* THE FUN BEGINS HERE *)
- if not error1 then
- begin
- textwd := picwd*unitlngth + 15.0; (* in mm *)
- if (textwd < 170) then textwd := 170;
- if textwd >240
- then begin
- writeln('% *****************************************************');
- writeln('% max-possible-picwd is about 240mm which will have ');
- writeln('% to be in Landscape. You''ll have to reduce scales.');
- writeln('% *****************************************************')
- end
- else if textwd > 170 then
- begin
- writeln('% *****************************************************');
- writeln('% THIS TEXT IS A BIT TOO WIDE FOR VERTICAL PAPER MODE.');
- writeln('% YOU WILL HAVE TO USE LANDSCAPE MODE TO PRINT.');
- writeln('% *****************************************************')
- end;
-
- if prepost[1] = 'y' then
- begin
- writeln('\documentstyle{article}');
- writeln('\setlength{\textwidth}{',textwd:1:2,'mm}');
- writeln('\pagestyle{empty} % => no page number ');
- writeln('\begin{document}');
- writeln;
- end; (* end prepost *)
-
- write('\newcommand{\xaxis}{'); strwrite(Xaxisstrg);
- writeln('} % the literal for X-axis');
- write('\newcommand{\yaxis}{'); strwrite(Yaxisstrg);
- writeln('} % the literal for Y-axis');
- c := 'A';
- while (plotstuff[c].chardef[1] <> 'n') and (c <= maxchar) do
- begin
- write('\newcommand{\pchar',c,'}');
- strwrite(plotstuff[c].chardef); writeln;
- c := chr(ord(c) + 1)
- end;
- writeln;
- write('\begin'); strwrite(fontname); writeln; (* fontname contains braces*)
- writeln('\begin{figure}[p] %you might want different options here');
-
- (* XGorig & YGorig refer to the origin of the graph. *)
- (* XP1orig & YP1orig refer to the bottom-left origin of the picture box.*)
- (* XP2orig & YP2orig refer to the bottom-right corner of the picture box.*)
- (* see if (0,0) is on the graph or not *)
- XGorig := 0; YGorig := 0;
- if XP1orig >= 0 then XGorig := XP1orig
- else if (picwd + XP1orig) < 0 then XGorig := XP1orig + picwd;
- if YP1orig >= 0 then YGorig := YP1orig
- else if (picht + YP1orig) < 0 then YGorig := YP1orig + picht;
- XP2orig := picwd + XP1orig;
- YP2orig := picht + YP1orig;
- writeln('\unitlength = ',unitlngth:1:2,'mm');
- writeln('\begin{center}');
- writeln('\begin{picture}(',(picwd+10):1,',',(picht+10):1,')(',
- (XP1orig-5):1,',',(YP1orig-5):1,')');
- (* need a box of +10 on both axes to account for -10 origins & to *)
- (* get proper centering *)
- writeln('\thicklines');
- (* plot the horizontal axis *)
- if (XP2orig - XGorig) > 0 then
- begin
- writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(1,0){',
- abs(XP2orig-XGorig):1,'}}');
- writeln('\put(',(XP2orig+2):1,',',YGorig:1,'){\makebox(0,0)[l]{X}}')
- end;
- if (XGorig - XP1orig) > 0 then
- begin
- writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(-1,0){',
- abs(XGorig-XP1orig):1,'}}');
- writeln('\put(',(XP1orig-2):1,',',YGorig:1,
- '){\makebox(0,0)[r]{X}}')
- end;
- (* plot the vertical axis *)
- if (YP2orig - YGorig) > 0 then
- begin
- writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(0,1){',
- abs(YP2orig-YGorig):1,'}}');
- writeln('\put(',XGorig:1,',',(YP2orig+2):1,'){\makebox(0,0)[b]{Y}}')
- end;
- if (YGorig - YP1orig) > 0 then
- begin
- writeln('\put(',XGorig:1,',',YGorig:1,'){\vector(0,-1){',
- abs(YGorig-YP1orig):1,'}}');
- writeln('\put(',XGorig:1,',',(YP1orig-2):1,
- '){\makebox(0,0)[t]{Y}}')
- end;
- writeln('\thinlines');
-
- (*********************************************************************)
- (*the following put numbers & bars along X-axis and Y-axis *)
- (*********************************************************************)
- putbars(true,XGorig,(YGorig-1),Xdeltabar,abs(XP2orig-XGorig));
- putbars(true,XGorig,(YGorig-1),-Xdeltabar,abs(XGorig-XP1orig));
- putbars(false,(XGorig-1),YGorig,Ydeltabar,abs(YP2orig-YGorig));
- putbars(false,(XGorig-1),YGorig,-Ydeltabar,abs(YGorig-YP1orig));
-
- (* Before invoking putnumbers, we must explicitly check if it needs to
- be invoked at all. This is because in the procedure putnumbers I use
- absolute values as the stopping condition for while loop.
- We use absolute values in the procedure so as to handle plotting
- numbers on both the positive and negative halves of the axes.
- deln below represents the delta graph units corresponding to X|Ydeltanum.
- *)
- writeln('% Add a line similar to next one if number at origin desired.');
- deln := (Xscalereal*Xdeltanum) / Xscalegraph;
- pos := XGorig + Xdeltanum; num:=Xorignum + deln;
- if pos < XP2orig then
- putnumbers(true,(YGorig-2),pos,num,deln,Xdeltanum,XP2orig);
- pos := XGorig - Xdeltanum; num:=Xorignum - deln;
- if pos > XP1orig then
- putnumbers(true,(YGorig-2),pos,num,-deln,-Xdeltanum,XP1orig);
-
- deln := ( Yscalereal*Ydeltanum) / Yscalegraph;
- pos := YGorig + Ydeltanum; num:=Yorignum + deln;
- if pos < YP2orig then
- putnumbers(false,(XGorig-2),pos,num,deln,Ydeltanum,YP2orig);
- pos := YGorig - Ydeltanum; num:=Yorignum - deln;
- if pos > YP1orig then
- putnumbers(false,(XGorig-2),pos,num,-deln,-Ydeltanum,YP1orig);
-
- (***********************)
- (* put the legend box *)
- (***********************)
- if (legendloc <> 'no') then
- begin (* and if it is then obviously do nothing *)
- if (Xlegloc = -999999) and (Ylegloc = -999999) then
- begin (* implies explicit coordinates not specified *)
- (* if they are then they are set in legendread *)
- Xlegloc := picwd div 2; (* default is center *)
- Ylegloc := picht div 2; (* default is center *)
- if (legendloc[1] = 't') or (legendloc[2] = 't')
- then if YP2orig > 0 then Ylegloc := picht else Ylegloc := picht-10;
- if (legendloc[1] = 'b') or (legendloc[2] = 'b')
- then if YP1orig >= 0 then Ylegloc := 10 else Ylegloc := 0;
- if (legendloc[1] = 'l') or (legendloc[2] = 'l')
- then if XP1orig >= 0 then Xlegloc := 10 else Xlegloc := 0;
- if (legendloc[1] = 'r') or (legendloc[2] = 'r')
- then if XP2orig > 0 then Xlegloc := picwd else Xlegloc := picwd-10;
- Xlegloc := Xlegloc + XP1orig;
- Ylegloc := Ylegloc + YP1orig
- end;
-
- write('\put(',Xlegloc:1,',',Ylegloc:1,'){\makebox(0,0)');
- i:= 1; write('[');
- while (i <= 2) do
- begin
- if (legendloc[i] <> ' ') and (legendloc[i] <> '/') then
- write(legendloc[i]);
- i:=i+1
- end;
- write(']');
- writeln('{\fbox{\shortstack[l]{');
- c:='A';
- while (plotstuff[c].chardef[1] <> 'n') and (c <= maxchar) do
- begin
- write(' {\makebox(4,2)[lb]{\put(2,1){\pchar',c,'}}}: ');
- strwrite(plotstuff[c].charname); writeln('\\');
- c := chr(ord(c) + 1)
- end;
- writeln(' {\makebox(4,4)[b]{X}}: \xaxis \\');
- writeln(' {\makebox(4,2)[b]{Y}}: \yaxis');
- writeln(' }}}}')
- end; (* not 'no' of legendloc*)
-
- (* put the caption if explicit *)
- captiontwo[1]:=capstring[1];
- captiontwo[2]:=capstring[2];
- if captiontype[1] = 'e' then (* "e"xplicit, anything else other than *)
- (* "L" for LaTeX => no *)
- if captiontwo = 'YX' then
- begin
- writeln('% if the caption line is longer than the graphwidth, comment');
- writeln('% out the second line and use first one. you might have to');
- writeln('% fiddle with the width of parbox in the second stmt.');
- write('%\put(',XP1orig:1,',',(YP1orig-18):1,
- '){\makebox(',picwd:1,',0)[tl]{');
- writeln('Figure ',fignumber,'$\!$: \parbox[t]{',(textwd-32):1:1,'mm}{%');
- write('\put(',XP1orig:1,',',(YP1orig-18):1,
- '){\makebox(',picwd:1,',0)[t]{');
- writeln('Figure ',fignumber,'$\!$: {%');
- writeln('%\yaxis\ vs.\ \xaxis}}}')
- end
- else (* means explicit string is specified *)
- begin
- write('%\put(',XP1orig:1,',',(YP1orig-18):1,
- '){\makebox(',picwd:1,',0)[tl]{');
- writeln('Figure ',fignumber,'$\!$: \parbox[t]{',(textwd-32):1:1,'mm}{%');
- write('\put(',XP1orig:1,',',(YP1orig-18):1,
- '){\makebox(',picwd:1,',0)[t]{');
- writeln('Figure ',fignumber,'$\!$: {%');
- strwrite(capstring); writeln;
- writeln('}}}');
- end;
-
- writeln('% beginning of data');
- while not eof do
- begin
- readln(plotchar,xreality,yreality);
- xgraph := (xreality*Xscalegraph)/Xscalereal;
- ygraph := (yreality*Yscalegraph)/Yscalereal;
- writeln('\put(',xgraph:1:5,',',ygraph:1:5,'){\pchar',plotchar,'}')
- end;
- writeln('% end of data');
- writeln('\end{picture}');
- writeln('\end{center}');
-
- (* put the LaTeX \caption if so specified *)
- if captiontype[1] = 'L' then (* "L"aTeX . if it is not = 'L' or 'e'*)
- (* then interpreted as 'no' *)
- begin
- writeln('% if the caption line is longer than the graphwidth,use a');
- writeln('% \parbox[t]{...mm}{.......} like statement for the argument');
- writeln('% with suitable args for parbox to get things centered.');
- if captiontwo = 'YX'
- then begin
- writeln('% You might want to add a [] to \caption below.');
- writeln('\caption{\protect\normalsize \yaxis\ vs.\ \xaxis }')
- end
- else begin
- writeln('\caption{\protect\normalsize ');
- strwrite(capstring); writeln;
- writeln('}')
- end;
- if labelname[1] = '{' then (* anything else => 'no' *)
- begin
- write('\label'); strwrite(labelname); writeln
- (* labelname contains the braces *)
- end
- end;
-
- writeln('\end{figure}');
- writeln; (* a blank line is supposedly needed before \end fontname *)
- (* so says the latex manual *)
- write('\end'); strwrite(fontname); writeln; (* fontname contains braces *)
- writeln;
-
- if prepost[1] = 'y' then
- writeln('\end{document}');
- end (* not error1 *)
- end.
-